package uk.co.richardwkirk.funnels;

import uk.co.richardwkirk.display.FunnelDisplay;
import uk.co.richardwkirk.funnels.controllers.FinishController;
import uk.co.richardwkirk.funnels.controllers.FunnelController;
import uk.co.richardwkirk.funnels.model.FunnelSystem;
import uk.co.richardwkirk.funnels.model.RaceFinisherException;
import uk.co.richardwkirk.funnels.model.RaceFinishers;

public class FunnelTest {

	public long TIME_INCREMENT = 1;
	
	String resultsFile = null;
	
	// The funnel system records where the runners are after they finish
	FunnelSystem funnels = null;

	// Funnel display!
	FunnelDisplay display = null;
	
	// The finishers list tells us when each runner will cross the line
	RaceFinishers finishers = null;
	
	// Controllers are used to step through time and set the state of the funnels
	FinishController finishControl = null;
	FunnelController funnelControl = null;	
	
	public FunnelTest(FunnelSettings settings, String resultsFile_) throws RaceFinisherException
	{
		this.resultsFile = resultsFile_;
		
		// Initialise the funnel system for the test
		// using the results file we have loaded
		init(settings);
		
	}

	
	public void setDisplay(FunnelDisplay newDisplay) {
		// Assign the funnels to the display
		display = newDisplay;
		display.setFunnels(funnels);
	}


	protected void init(FunnelSettings settings) throws RaceFinisherException
	{
		// The funnel system records where the runners are after they finish
		funnels = new FunnelSystem(settings);
		
		// The finishers list tells us when each runner will cross the line
		finishers = RaceFinishers.createFromResource(resultsFile);
		System.out.println("Loaded " + finishers.size() + " finishers.");
		
		// Controllers are used to step through time and set the state of the funnels
		finishControl = new FinishController(finishers, funnels);
		funnelControl = new FunnelController(funnels, settings);
	}
	
	
	public void runTest()
	{
		boolean overflow = false;
		long currentTime = 0;
		while (!finishers.allFinished() || !funnels.isEmpty())
		{
			// Increment the time in the controllers
			currentTime += TIME_INCREMENT;
			finishControl.incrementTime(TIME_INCREMENT);
			funnelControl.incrementTime(TIME_INCREMENT);
			
			if (!overflow && funnels.hasOverflowed())
			{
				display.setOverflowed(true);
				overflow = true;
			}
			
			// Show the time
			display.setTime(currentTime);
			
			// Re-display the state of the funnel
			display.update();
		}
		
		display.setStatus("Scenario completed.");
	}

}
